home *** CD-ROM | disk | FTP | other *** search
/ Reverse Code Engineering RCE CD +sandman 2000 / ReverseCodeEngineeringRceCdsandman2000.iso / RCE / Library / Manuels & Misc / Assembly / AOA.ZIP / CH10 / MOON.ASM < prev   
Encoding:
Assembly Source File  |  1996-02-08  |  8.1 KB  |  362 lines

  1. ; Simple "Moon Lander" game.
  2. ;
  3. ; Randall Hyde
  4. ; 2/8/96
  5. ;
  6. ; This program is an example of a trivial little "moon lander"
  7. ; game that simulates a Lunar Module setting down on the Moon's
  8. ; surface.  At time T=0 the spacecraft's velocity is 1000 ft/sec
  9. ; downward, the craft has 1000 units of fuel, and the craft is
  10. ; 10,000 ft above the moon's surface.  The pilot (user) can 
  11. ; specify how much fuel to burn at each second.
  12. ;
  13. ; Note that all calculations are approximate since everything is
  14. ; done with integer arithmetic.
  15.  
  16.  
  17. ; Some important constants
  18.  
  19. InitialVelocity    =    1000
  20. InitialDistance    =    10000
  21. InitialFuel    =    250
  22. MaxFuelBurn    =    25
  23.  
  24. MoonsGravity    =    5        ;Approx 5 ft/sec/sec
  25. AccPerUnitFuel    =    -5        ;-5 ft/sec/sec for each fuel unit.
  26.  
  27.  
  28.         .xlist
  29.         include     stdlib.a
  30.         includelib    stdlib.lib
  31.         .list
  32.  
  33.         .386            ;Comment out these two statements
  34.         option    segment:use16    ; if you are not using an 80386.
  35.  
  36. dseg        segment    para public 'data'
  37.  
  38. ; Current distance from the Moon's Surface:
  39.  
  40. CurDist        word    InitialDistance
  41.  
  42. ; Current Velocity:
  43.  
  44. CurVel        word    InitialVelocity
  45.  
  46. ; Total fuel left to burn:
  47.  
  48. FuelLeft    word    InitialFuel
  49.  
  50.  
  51. ; Amount of Fuel to use on current burn.
  52.  
  53. Fuel        word    ?
  54.  
  55. ; Distance travelled in the last second.
  56.  
  57. Dist        word    ?
  58.  
  59. dseg        ends
  60.  
  61. cseg        segment    para public 'code'
  62.         assume    cs:cseg, ds:dseg
  63.  
  64. ; GETI-    Reads an integer variable from the user and returns its
  65. ;    its value in the AX register.  If the user entered garbage,
  66. ;    this code will make the user re-enter the value.
  67.  
  68. geti        textequ    <call _geti>
  69. _geti        proc
  70.         push    es
  71.         push    di
  72.         push    bx
  73.  
  74. ; Read a string of characters from the user.
  75. ;
  76. ; Note that there are two (nested) loops here.  The outer loop
  77. ; (GetILp) repeats the getsm operation as long as the user 
  78. ; keeps entering an invalid number.  The innermost loop (ChkDigits)
  79. ; checks the individual characters in the input string to make
  80. ; sure they are all decimal digits.
  81.  
  82. GetILp:        getsm
  83.  
  84. ; Check to see if this string contains any non-digit characters:
  85. ;
  86. ; while (([bx] >= '0') and ([bx] <= '9')  bx := bx + 1;
  87. ;
  88. ; Note the sneaky way of turning the while loop into a
  89. ; repeat..until loop.
  90.  
  91.         mov    bx, di        ;Pointer to start of string.
  92.         dec    bx
  93. ChkDigits:    inc    bx
  94.         mov    al, es:[bx]    ;Fetch next character.
  95.         IsDigit            ;See if it's a decimal digit.
  96.         je    ChkDigits    ;Repeat if it is.
  97.  
  98.         cmp    al, 0        ;At end of string?
  99.         je    GotNumber
  100.  
  101. ; Okay, we just ran into a non-digit character.  Complain and make
  102. ; the user reenter the value.
  103.  
  104.         free            ;Free space malloc'd by getsm.
  105.         print
  106.         byte    cr,lf
  107.         byte    "Illegal unsigned integer value, "
  108.         byte    "please reenter.",cr,lf
  109.         byte    "(no spaces, non-digit chars, etc.):",0
  110.         jmp    GetILp
  111.  
  112.  
  113. ; Okay, ES:DI is pointing at something resembling a number.  Convert
  114. ; it to an integer.
  115.  
  116. GotNumber:    atoi
  117.         free            ;Free space malloc'd by getsm.
  118.  
  119.         pop    bx
  120.         pop    di
  121.         pop    es
  122.         ret
  123. _geti        endp
  124.  
  125.  
  126.  
  127.  
  128.  
  129. ; InitGame-    Initializes global variables this game uses.
  130.  
  131. InitGame    proc
  132.         mov    CurVel, InitialVelocity
  133.         mov    CurDist, InitialDistance
  134.         mov    FuelLeft, InitialFuel
  135.         mov    Dist, 0
  136.         ret
  137. InitGame    endp
  138.  
  139.  
  140. ; DispStatus-    Displays important information for each
  141. ;        cycle of the game (a cycle is one second).
  142.  
  143. DispStatus    proc
  144.         printf
  145.         byte    cr,lf
  146.         byte    "Distance from surface: %5d",cr,lf
  147.         byte    "Current velocity:      %5d",cr,lf
  148.         byte    "Fuel left:             %5d",cr,lf
  149.         byte    lf
  150.         byte    "Dist travelled in the last second: %d",cr,lf
  151.         byte    lf,0
  152.         dword    CurDist, CurVel, FuelLeft, Dist
  153.         ret
  154. DispStatus    endp
  155.  
  156.  
  157. ; GetFuel-    Reads an integer value representing the amount of fuel
  158. ;        to burn from the user and checks to see if this value
  159. ;        is reasonable.  A reasonable value must:
  160. ;
  161. ;        * Be an actual number (GETI handles this).
  162. ;        * Be greater than or equal to zero (no burning
  163. ;          negative amounts of fuel, GETI handles this).
  164. ;        * Be less than MaxFuelBurn (any more than this and
  165. ;          you have an explosion, not a burn).
  166. ;        * Be less than the fuel left in the Lunar Module.
  167.  
  168. GetFuel        proc
  169.         push    ax
  170.  
  171. ; Loop..endloop structure that reads an integer input and terminates
  172. ; if the input is reasonable.  It prints a message an repeats if
  173. ; the input is not reasonable.
  174. ;
  175. ; loop
  176. ;    get fuel;
  177. ;    if (fuel < MaxFuelBurn) then break;
  178. ;    print error message.
  179. ; endloop
  180. ;
  181. ; if (fuel > FuelLeft) then
  182. ;
  183. ;    fuel = fuelleft;
  184. ;    print appropriate message.
  185. ;
  186. ; endif
  187.  
  188. GetFuelLp:    print
  189.         byte    "Enter amount of fuel to burn: ",0
  190.         geti
  191.         cmp    ax, MaxFuelBurn
  192.         jbe    GoodFuel
  193.  
  194.         print
  195.         byte    "The amount you've specified exceeds the "
  196.         byte    "engine rating,", cr, lf
  197.         byte    "please enter a smaller value",cr,lf,lf,0
  198.         jmp    GetFuelLp
  199.  
  200. GoodFuel:    mov    Fuel, ax
  201.         cmp    ax, FuelLeft
  202.         jbe    HasEnough
  203.         printf
  204.         byte    "There are only %d units of fuel left.",cr,lf
  205.         byte    "The Lunar module will burn this rather than %d"
  206.         byte    cr,lf,0
  207.         dword    FuelLeft, Fuel
  208.  
  209.         mov    ax, FuelLeft
  210.         mov    Fuel, ax
  211.  
  212. HasEnough:    mov    ax, FuelLeft
  213.         sub    ax, Fuel
  214.         mov    FuelLeft, ax
  215.         pop    ax
  216.         ret
  217. GetFuel        endp
  218.  
  219.  
  220.  
  221. ; ComputeStatus-
  222. ;
  223. ;    This routine computes the new velocity and new distance based on the
  224. ;    current distance, current velocity, fuel burnt, and the moon's
  225. ;    gravity.  This routine is called for every "second" of flight time.
  226. ;
  227. ; note:
  228. ;
  229. ;    Distance Travelled = Acc*T*T/2 + Vel*T  (note: T=1, so it goes away).
  230. ;    Acc = MoonsGravity + Fuel * AccPerUnitFuel
  231. ;
  232. ;    New Velocity = Acc*T + Prev Velocity
  233. ;
  234. ;     This code should really average these values over the one second
  235. ;    time period, but the simulation is so crude anyway, there's no
  236. ;    need to really bother.
  237.  
  238. ComputeStatus    proc
  239.         push    ax
  240.         push    bx
  241.         push    dx
  242.  
  243. ; First, compute the acceleration value based on the fuel burnt
  244. ; during this second (Acc = Moon's Gravity + Fuel * AccPerUnitFuel).
  245.  
  246.         mov    ax, Fuel        ;Compute
  247.         mov    dx, AccPerUnitFuel    ; Fuel*AccPerUnitFuel
  248.         imul    dx
  249.  
  250.         add    ax, MoonsGravity    ;Add in Moon's gravity.
  251.         mov    bx, ax            ;Save Acc value.
  252.  
  253. ; Now compute the new velocity (V=AT+V)
  254.  
  255.         add    ax, CurVel        ;Compute new velocity
  256.         mov    CurVel, ax
  257.  
  258. ; Next, compute the distance travelled (D = 1/2 * A * T^2 + VT +D)
  259.  
  260.         sar    bx, 1            ;Acc/2
  261.         add    ax, bx            ;Acc/2 + V (T=1!)
  262.         mov    Dist, ax        ;Distance Travelled.
  263.         neg    ax
  264.         add    CurDist, ax        ;New distance.
  265.         
  266.         pop    dx
  267.         pop    bx
  268.         pop    ax
  269.         ret
  270. ComputeStatus    endp
  271.  
  272.  
  273. ; GetYorN-    Reads a yes or no answer from the user (Y, y, N, or n).
  274. ;        Returns the character read in the al register (Y or N,
  275. ;        converted to upper case if necessary).
  276.  
  277. GetYorN        proc
  278.         getc
  279.         ToUpper
  280.         cmp    al, 'Y'
  281.         je    GotIt
  282.         cmp    al, 'N'
  283.         jne    GetYorN
  284. GotIt:        ret
  285. GetYorN        endp
  286.  
  287.         
  288.  
  289.  
  290. Main        proc
  291.         mov    ax, dseg
  292.         mov    ds, ax
  293.         mov    es, ax
  294.         meminit
  295.  
  296. MoonLoop:    print
  297.         byte    cr,lf,lf
  298.         byte    "Welcome to the moon lander game.",cr,lf,lf
  299.         byte    "You must manuever your craft so that you touch"
  300.         byte    "down at less than 10 ft/sec",cr,lf
  301.         byte    "for a soft landing.",cr,lf,lf,0
  302.  
  303.         call    InitGame
  304.  
  305. ; The following loop repeats while the distance to the surface is greater
  306. ; than zero.
  307.  
  308. WhileStillUp:    mov    ax, CurDist
  309.         cmp    ax, 0
  310.         jle    Landed
  311.  
  312.         call    DispStatus
  313.         call    GetFuel
  314.         call    ComputeStatus
  315.         jmp    WhileStillUp
  316.  
  317. Landed:        cmp    CurVel, 10
  318.         jle    SoftLanding
  319.  
  320.         printf
  321.         byte    "Your current velocity is %d.",cr,lf
  322.         byte    "That was just a little too fast.  However, as a "
  323.         byte    "consolation prize,",cr,lf
  324.         byte    "we will name the new crater you just created "
  325.         byte    "after you.",cr,lf,0
  326.         dword    CurVel
  327.  
  328.         jmp    TryAgain
  329.  
  330. SoftLanding:    printf
  331.         byte    "Congrats!  You landed the Lunar Module safely at "
  332.         byte    "%d ft/sec.",cr,lf
  333.         byte    "You have %d units of fuel left.",cr,lf
  334.         byte    "Good job!",cr,lf,0
  335.         dword    CurVel, FuelLeft
  336.  
  337. TryAgain:    print
  338.         byte    "Do you want to try again (Y/N)? ",0
  339.         call    GetYorN
  340.         cmp    al, 'Y'
  341.         je    MoonLoop
  342.  
  343.         print
  344.         byte    cr,lf
  345.         byte    "Thanks for playing!  Come back to the moon again sometime"
  346.         byte    cr,lf,lf,0
  347.     
  348.  
  349. Quit:        ExitPgm            ;DOS macro to quit program.
  350. Main        endp
  351.  
  352. cseg        ends
  353.  
  354. sseg        segment    para stack 'stack'
  355. stk        byte    1024 dup ("stack   ")
  356. sseg        ends
  357.  
  358. zzzzzzseg    segment    para public 'zzzzzz'
  359. LastBytes    byte    16 dup (?)
  360. zzzzzzseg    ends
  361.         end    Main
  362.